#Imports for our mod to work
import es, playerlib, gamethread, popuplib, cPickle, os.path, wcsconfig, time, random
from wcsconfig import *

info = es.AddonInfo()
info.name = 'WarCraft: Source'
info.version = '0.5 Python'
info.url = 'www.wc3source.de/board'
info.basename = 'wcs'
info.author = 'Jeff Hoogland & Steven Hartin (J3ff & Freddukes)'

#Defines some default values
race_folder = es.getAddonPath('wcs') + '/races'
race_list = []
colors = { 'red': ['255','0','0'], 
	'blue': ['0','0','255'], 
	'green': ['0','255','0'], 
	'magenta': ['139','0','139'], 
	'brown': ['128','42','42'], 
	'grey': ['128','128','128'], 
	'cyan':  ['0','204','204'], 
	'yellow': ['255','255','0'], 
	'orange': ['255','127','0'], 
	'white': ['255','255','255'],
	'pink': ['255','0','204']
	}
es.ServerVar('wcs_x').set(0)
es.ServerVar('wcs_y').set(0)
es.ServerVar('wcs_z').set(0)
es.ServerVar('wcs_temp').set(0)

es.ServerVar('wcs_version',info.version,'WarCraft: Source Version - Made by Jeff & freddukes').makepublic()

#Run when our mod is loaded
def load():
	if not es.exists('command', 'wcs'):
		es.regcmd('wcs', 'wcs/wcscommand')
	if not es.exists('saycommand', 'wcs'):
		es.regsaycmd('wcs', 'wcs/wcsChatCommand')
	if not es.exists('clientcommand', 'wcs'):
		es.regclientcmd('wcs', 'wcs/wcsChatCommand')
	if not es.exists('clientcommand','+ultimate'):
		es.regclientcmd('+ultimate','wcs/wcsUltiOn')
	if not es.exists('clientcommand','-ultimate'):
		es.regclientcmd('-ultimate','wcs/wcsUltiOff')
	if not es.exists('clientcommand','+ability'):
		es.regclientcmd('+ability','wcs/AbilityOn','Turns the WCS ability one')
	if not es.exists('clientcommand','-ability'):
		es.regclientcmd('-ability','wcs/AbilityOff','Turns the WCS ability off')
	es.loadevents('declare', 'addons/eventscripts/wcs/events/events.res')
	str_path = es.getAddonPath('wcs') + '/UserSaves.db'
	if os.path.isfile(str_path):
		global _dict_WCSPlayers
		file_users = open(str_path)
		_dict_WCSPlayers = cPickle.load(file_users)
		file_users.close()
	if os.path.isfile(es.getAddonPath('wcs') + '/WCSRaceLoader.cfg'):
		es.server.cmd('es_xmexec ../addons/eventscripts/wcs/WCSRaceLoader.cfg')
	else:
		es.dbgmsg(0,'WCS: ERROR - Unable to load WCSRaceLoader.cfg! Please ensure it is in the ./wcs/ directory.')
	es.load('wcs/admin')
	es.load('wcs/shopmenu')
	a = popuplib.create('wcsshopmenu')
	a.addline('WarCraft Shopmenu')
	a.addline('-----------------')
	a.addline('->1. Enhancements')
	a.addline('->2. Powerups')
	a.addline('->3. Attacks')
	a.addline('->4. Defenses')
	a.addline('->5. Specials')
	a.addline('-----------------')
	a.addline('0. Cancel')
	a.submenu(1,'wcsenhancementmenu')
	a.submenu(2,'wcspowerupmenu')
	a.submenu(3,'wcsattackmenu')
	a.submenu(4,'wcsdefensemenu')
	a.submenu(5,'wcsspecialmenu')
def unload():
	es.unregsaycmd('wcs')
	es.unregclientcmd('wcs')
	for race in race_list:
		es.unload('wcs/races/%s'%race)
	es.unload('wcs/admin')
	es.unload('wcs/shopmenu')
#Handels all of our different wcs chat commands
def wcsChatCommand():
	userid = int(es.getcmduserid())
	dead = playerlib.getPlayer(userid).get('isdead')
	race = GetRace(userid)
	playerkey = getSteam(userid)[race]
	skilllist = Race(race).returnSkillList()
	arg1 = es.getargv(1).lower()
	if arg1 == 'changerace':
		racemenu.send(userid)
	elif arg1 == 'spendskills':
		spendskills(userid)
	elif arg1 == 'help':
		helpmenu(userid)
	elif arg1 == 'resetskills':
		if dead:
			for skill in skilllist:
				playerkey['unspent skills'] += playerkey[skill]
				playerkey[skill] = 0
			es.tell(userid, '#multi', '#defaultYou now have #green%s #defaultunspent skills points.'%playerkey['unspent skills'])
		else:
			es.tell(userid, '#multi', '#defaultYou may only use #lightgreenresetskills #defaultwhile dead.')
	elif arg1 == 'showxp':
		es.tell(userid, '#multi', '#defaultRace: #green%s #defaultLevel #green%s #defaultXp #green%s #lightgreen/ #green %s'%(race, playerkey['level'], playerkey['xp'], start_your_engines+((playerkey['level']-1)*levelinterval)))
	elif arg1 == 'showskills':
		skillsmenu = popuplib.create('skillsmenu')
		skillsmenu.addline('%s Skills List:'%es.getplayername(userid))
		for skill in skilllist:
			skillsmenu.addline('%s : %s'%(skill, playerkey[skill]))
		skillsmenu.send(userid)
	elif arg1 == 'raceinfo':
		raceinfomenu.send(userid)
	elif arg1 == 'admin':
		steamid = es.getplayersteamid(userid) # The only time you can use steamid!
		if steamid in wcs_admins:
			popuplib.send('wcsadminmenu',userid)
		else:
			es.tell(userid,'#green','Sorry you are not authorized to run the command admin')
	elif arg1 == 'shopmenu':
		popuplib.send('wcsshopmenu',userid)
	elif arg1 == 'rank':
		try:
			user = es.getuserid(es.getargv(2))
			if user:
				SendRank(user)
		except IndexError:
				SendRank(userid)
	elif arg1 == 'top10':
		a = sorted(_dict_WCSPlayers,WcsSort)
		index = 0
		top5 = popuplib.create('top5')
		top5.addline('=== WarCraft:Source Top10 ===')
		top5.addline('        Ranks 1 - %s       '%('5' if len(a) >= 5 else len(a)))
		top5.addline('-----------------------')
		while index < 5:
			try:
				steam = a[index]
				index += 1
				d = _dict_WCSPlayers
				name = d[steam]['name']
				level = d[steam]['level']
				race = d[steam]['race']
				if len(name) > 16:
					name = name[0:14]+'...'
					format = '->%s. %s - Level: %s Race: %s'%(index, name, level, race)
					top5.addline(format)
			except IndexError:
				index += 1
				top5.addline(' ')
		top5.addline('-----------------------')
		top5.addline(' ')
		if len(a) > 5: top5.addline('9. Rank 6 - %s'%('10' if len(a) >= 10 else len(a)))
		top5.addline('0. Cancel')
		if len(a) > 5: 
			top5.submenu(9,'top10')
			top10 = popuplib.create('top10')
			top10.addline('=== WarCraft:Source Top10 ===')
			top10.addline('        Ranks 6 - %s      '%('10' if len(a) >= 10 else len(a)))
			top10.addline('-----------------------')
			while index < 10:
				try:
					steam = a[index]
					index += 1
					d = _dict_WCSPlayers
					name = d[steam]['name']
					level = d[steam]['level']
					race = d[steam]['race']
					if len(name) > 16:
						name = name[0:14]+'...'
						format = '->%s. %s - Level: %s Race: %s'%(index, name, level, race)
						top10.addline(format)
				except IndexError:
					index += 1
					top10.addline(' ')
			top10.addline('-----------------------')
			top10.addline('8. Rank 1 - 5')
			top10.addline(' ')
			top10.addline('0. Cancel')
			top10.submenu(8,'top5')
		top5.send(userid)
	else:
		es.tell(userid, '#multi', '#defaultSorry but #lightgreen%s #defaultis not a valid WC:Source command.'%arg1)
#Runs our wcs console command
def wcscommand():
	arg1 = es.getargv(1).lower()
	if arg1 == 'load':
		race = es.getargv(2)
		if racecheck(race):
			race_list.append(race)
			es.load('wcs/races/%s'%race)
			buildracemenu()
	elif arg1 == 'unload':
		race = es.getargv(2)
		if racecheck(race):
			race_list.remove(race)
			es.unload('wcs/races/%s'%race)
			buildracemenu()
	elif arg1 == 'heal':
		Command(es.getargv(2)).Heal(es.getargv(3))
	elif arg1 == 'damage':
		userid = int(es.getargv(2))
		if userid:
			amount = int(es.getargv(3))
			es.server.queuecmd('damage %s %s'%(userid,amount))
		else:
			es.tell(userid, '#multi', '#defaultSorry but #lightgreen%s #defaultis not a valid WC:Source command.'%arg1)
	else:
		es.tell(userid, '#multi', '#defaultSorry but #lightgreen%s #defaultis not a valid WC:Source command.'%arg1)
#Checks to see if the given race name has a .py file in the races sub folder
def racecheck(race):
	if os.path.isfile(race_folder + '/%s/%s.py'%(race, race)):
		return 1
	else:
		es.dbgmsg(0,'WCS ERROR: Cannot find race %s'%race)
		return 0
#Builds our spend skills menu
def spendskills(userid):
	playerrace = GetRace(userid)
	playerkey = getSteam(userid)[playerrace]
	if playerkey['unspent skills']:
		playerlevel = playerkey['level']
		skillskey = Race(playerrace).returnRaceKey()['skills']
		spendmenu = popuplib.easymenu('spendmenu', '_popup_choice', spendSelect)
		spendmenu.settitle('You have %s Unspent Skills - Spend a Rank Into:'%playerkey['unspent skills'])
		for skill in Race(playerrace).returnSkillList():
			currentranks = playerkey[skill]
			if skillskey[skill]['type'] == 'Skill':
				if currentranks < skillskey[skill]['levels']:
					intcheck = intervalCheck(currentranks, skillskey[skill]['interval'], playerlevel)
					if intcheck == 1:
						spendmenu.addoption((playerrace, skill), skill)
					else:
						option = '%s (Level Needed: %s)'%(skill, intcheck)
						spendmenu.addoption(('Low', intcheck, currentranks+1, skill), option, True)
				else:
					option = '%s (MAXED)'%skill
					spendmenu.addoption(('Max', skill), option,False)
					# Displays the text in white and makes it unselectable
			else:
				if currentranks < skillskey[skill]['levels']:
					requiredlevel = skillskey[skill]['required level']
					if playerlevel >= requiredlevel:
						intcheck = intervalCheck(currentranks, skillskey[skill]['interval'], playerlevel-requiredlevel)
						if intcheck == 1:
							spendmenu.addoption((playerrace, skill), skill)
						else:
							spendmenu.addoption(('Low', intcheck, currentranks+1, skill), '%s (Level Needed: %s)'%(skill, intcheck+requiredlevel))
					else:
						spendmenu.addoption(('Low', requiredlevel, currentranks+1, skill), '%s (Level Needed: %s)'%(skill, requiredlevel))
				else:
					option = '%s (MAXED)'%skill
					spendmenu.addoption(('Max', skill), option,False)
					# Displays the text in white and makes it unselectable
		spendmenu.send(userid)
	else:
		es.tell(userid, '#lightgreen', 'You do not have any unspent skill points at this time.')
def spendSelect(userid, choice, popupid):
	if choice[0] != 'Low':
		if choice[0] != 'Max':
			playerkey = getSteam(userid)[choice[0]]
			playerkey[choice[1]] += 1
			playerkey['unspent skills'] -= 1
			es.tell(userid, '#multi', "#lightgreen #green%s #lightgreenhas advanced to level #green%s#lightgreen."%(choice[1], playerkey[choice[1]]))
			if playerkey['unspent skills'] and es.getplayersteamid(userid) != "BOT":
				spendskills(userid)
		else:
			es.tell(userid, '#multi', "#defaultYour #green%s #defaultis already at it's max level."%(choice[1]))
			spendskills(userid)
	else:
		es.tell(userid, '#multi', '#lightgreenYou must be level #green%s #lightgreento advance #green%s #lightgreento rank #green%s#lightgreen.'%(choice[1], choice[3], choice[2]))
		spendskills(userid)
#Builds and shows our helpmenu
def helpmenu(userid):
	help = popuplib.create('help')
	help.addline('Chat/Console Commands:')
	help.addline(' wcs changerace - Select a new race to play as.')
	help.addline(' wcs raceinfo - See the differnet skills of each race.')
	help.addline(" wcs resetskills - Reset you current race's skills.")
	help.addline(' wcs spendskills - Spend unspent skill points.')
	help.addline(' wcs shopmenu - Buy items from a menu.')
	help.addline(' wcs help - This help menu.')
	help.send(userid)
#Determins if a user has enough levels to gain the level skill rank in a skill
def intervalCheck(ranks, interval, level):
	levelneeded = 1+(ranks*interval)
	if level >= levelneeded:
		return 1
	else:
		return levelneeded
#Builds our racemenu
def buildracemenu():
	if popuplib.exists('racemenu'):
		popuplib.delete('racemenu')
	if popuplib.exists('raceinfomenu'):
		popuplib.delete('raceinfomenu')
	global racemenu
	racemenu = popuplib.easymenu('racemenu', '_popup_choice', raceMenuSelect)
	racemenu.settitle('WCS Race Menu:')
	global raceinfomenu
	raceinfomenu = popuplib.easymenu('raceinfomenu', '_popup_choice', raceInfoSelect)
	raceinfomenu.settitle('WCS Race Info Menu:')
	for race in race_list:
		racekey = Race(race).returnRaceKey()
		if racekey.has_key('Min Level') and not racekey.has_key('Team'):
			racemenu.addoption(race, '%s (Level %i)'%(race, racekey['Min Level']))
			raceinfomenu.addoption(race, '%s (Level %i)'%(race, racekey['Min Level']))
		elif racekey.has_key('Team') and not racekey.has_key('Min Level'):
			racemenu.addoption(race, '%s (Team %i)'%(race, racekey['Team']))
			raceinfomenu.addoption(race, '%s (Team %i)'%(race, racekey['Team']))
		elif racekey.has_key('Team') and racekey.has_key('Min Level'):
			racemenu.addoption(race, '%s (Team %i, Level %i)'%(race, racekey['Team'], racekey['Min Level']))
			raceinfomenu.addoption(race, '%s (Team %i, Level %i)'%(race, racekey['Team'], racekey['Min Level']))
		else:
			racemenu.addoption(race, '%s'%race)
			raceinfomenu.addoption(race, '%s'%race)
	for userid in playerlib.getUseridList('#all'):
		racemenu.update(userid)
		raceinfomenu.update(userid)
#Handels what happens when a user selects a race
def raceMenuSelect(userid, choice, popupid):
	good = 1
	if Race(choice).returnRaceKey().has_key('Min Level'):
		if not getSteam(userid)['level'] >= Race(choice).returnRaceKey()['Min Level']:
			good = 0
			es.tell(userid, '#multi', '#defaultYou are not a high enough level to play as a #green%s#default.'%choice)
	if Race(choice).returnRaceKey().has_key('steam allow'):
		if not playerlib.uniqueid(userid,True) in Race(choice).returnRaceKey()['steam allow']:
			good = 0
			es.tell(userid, '#multi', '#green%s#default is restricted to what steamids may play it! And you are not one of them!'%choice)
	if Race(choice).returnRaceKey().has_key('teamlimit'):
		limit = Race(choice).returnRaceKey()['teamlimit']
		team = int(es.getplayerteam(userid))
		count = 0
		if team == 2:
			filter = '#t'
		elif team == 3:
			filter = '#ct'
		for id in playerlib.getUseridList(filter):
			if GetRace(id) == choice:
				count += 1
		if count >= limit:
			good = 0
			es.tell(userid, '#multi', '#defaultOnly %s number of players on each team may be a #green%s#default at the same time.'%(limit,choice))
	if good:
		if playerlib.getPlayer(userid).get('isdead'):
			getSteam(userid)['race'] = choice
			es.tell(userid, '#multi', '#defaultYou are now a #green%s'%choice)
			checkRace(userid, choice)
		else:
			getSteam(userid)['delayed race'] = choice
			es.tell(userid, '#multi', '#defaultYour race will be set to #green%s #defaultat the end of the round.'%choice)
#Handels what happens when some chooses an option in our raceinfo menu
def raceInfoSelect(userid, choice, popupid):
	skilllist = Race(choice).returnSkillList()
	infomenu = popuplib.create('infomenu')
	infomenu.addline('%s Skills:'%choice)
	infomenu.addline('-----------------------')
	index = 0
	for skill in skilllist:
		index += 1
		infomenu.addline('->%s. %s'%(index, skill))
		infomenu.addline('  - %s'%(Race(choice).returnRaceKey()['skills'][skill]['description']))
	infomenu.addline('-----------------------')
	infomenu.addline('0. Cancel')
	infomenu.send(userid)
#Global Events
def es_map_start(ev):
	es.loadevents('declare', 'addons/eventscripts/wcs/events/events.res')
	es.server.queuecmd('est_RegEventBlock player_spawn "es_xdoblock wcs/prep_spawn"')
# Delete the player if inactivity is too high
def est_map_end(ev):
	for a in _dict_WCSPlayers:
		time_now = time.time()
		last_active = _dict_WCSPlayers[a]['last_active']
		inactivity_length = inactivity_counter * 86400
		time_now -= inactivity_length
		if time_now >= last_active:
			del _dict_WCSPlayers[a]
def round_end(event_var):
	winner = int(event_var['winner'])
	if winroundxp:
		if winner == 2:
			for userid in playerlib.getUseridList('#t'):
				Command(int(userid)).GiveXp(winroundxp, 'your team winning the round')
		if winner == 3:
			for userid in playerlib.getUseridList('#ct'):
				Command(int(userid)).GiveXp(winroundxp, 'your team winning the round')
	for userid in playerlib.getUseridList('#all'):
		playerkey = getSteam(int(userid))
		if playerkey['delayed race']:
			playerkey['race'] = playerkey['delayed race']
			checkRace(userid, playerkey['race'])
			playerkey['delayed race'] = 0
			es.tell(int(userid), '#multi', '#defaultYour race is now #green%s#default.'%(playerkey['race']))
	str_path = open(es.getAddonPath('wcs') + '/UserSaves.db', 'w')
	cPickle.dump(_dict_WCSPlayers, str_path)
	str_path.close()
def hostage_rescued(event_var):
	if hostagexp:
		Command(event_var['userid']).GiveXp(hostagexp, 'saving a hostage')
def bomb_defused(event_var):
	if bombdefusexp:
		Command(event_var['userid']).GiveXp(bombdefusexp, 'defusing the bomb')
def bomb_planted(event_var):
	if bombplantxp:
		Command(event_var['userid']).GiveXp(bombplantxp, 'planting the bomb')
def bomb_exploded(event_var):
	if bombexplodexp:
		for userid in playerlib.getUseridList('#t,#alive'):
			Command(userid).GiveXp(bombexplodexp, 'defending the bomb.')
def player_spawn(event_var):
	playerkey = getSteam(event_var['userid'])
	if not playerkey.has_key('race'):
		if event_var['es_steamid'] != "BOT":
			es.changeteam(event_var['userid'],1)
			es.tell(event_var['userid'],'#green','You must first slect a race!')
			racemenu.send(userid)
		else:
			pass
	if announcexp:
		a = Command(event_var['userid'])
		xp = a.GetXp()
		level = a.GetLevel()
		nextxp = a.GetNextXp()
		race = GetRace(event_var['userid'])
		es.tell(event_var['userid'],'#multi','#greenYou are a level #lightgreen%s %s#green with #lightgreen%s/%s#green xp.'%(level,race,xp,nextxp))
#Handels for our custom events
def wcsUltiOn():
	userid = int(es.getcmduserid())
	if not es.getplayerprop(userid,'CCSPlayer.baseclass.pl.deadflag'):
		if not dict_commands.has_key(userid):
			Command(userid).ResetDefault()
		race = GetRace(userid)
		skilllist = Race(race).returnSkillList()
		for a in skilllist:
			if _dict_races[race]['skills'][a]['type'] == 'Ulti':
				skillname = str(a)
		cool_down_period = 0
		start_cool_down_time = 0
		if dict_commands[userid]['CoolDownTime'].has_key(skillname):
			cool_down_period = dict_commands[userid]['CoolDownTime'][skillname]['CoolTime']
			start_cool_down_time = dict_commands[userid]['CoolDownTime'][skillname]['start']
		time_elapsed = time.time() - start_cool_down_time
		if time_elapsed >= cool_down_period:
			es.event('initialize', 'player_ultimate_on')
			es_username = es.getplayername(userid)
			es_steamid = playerlib.uniqueid(userid,True)
			es.event('setint','player_ultimate_on','userid',userid)
			es.event('setstring','player_ultimate_on','es_steamid',es_steamid)
			es.event('setstring','player_ultimate_on','es_username',es_username)
			es.event('fire','player_ultimate_on')
		else:
			es.tell(userid,'#green','You cannot cast your ultimate for another %s seconds!'%(int(round(cool_down_period - time_elapsed))))
	else:
		es.tell(userid,'#green','You must be alive to cast \'ultimate\'')
def wcsUltiOff():
	userid = int(es.getcmduserid())
	es_username = es.getplayername(userid)
	es_steamid = playerlib.uniqueid(userid,True)
	es.event('initialize', 'player_ultimate_off')
	es.event('setint','player_ultimate_off','userid',userid)
	es.event('setstring','player_ultimate_off','es_steamid',es_steamid)
	es.event('setstring','player_ultimate_off','es_username',es_username)
	es.event('fire','player_ultimate_off')
# Handels our secondary command... +/- ability
def AbilityOn():
	userid = es.getcmduserid()
	steamid = es.getplayersteamid(userid)
	username = es.getplayername(userid)
	es.event('initialize', 'player_ability_on')
	es_username = es.getplayername(userid)
	es_steamid = playerlib.uniqueid(userid,True)
	es.event('setint','player_ability_on','userid',userid)
	es.event('setstring','player_ability_on','es_steamid',es_steamid)
	es.event('setstring','player_ability_on','es_username',es_username)
	es.event('fire','player_ability_on')
def AbilityOff():
	userid = es.getcmduserid()
	steamid = es.getplayersteamid(userid)
	username = es.getplayername(userid)
	es.event('initialize', 'player_ability_off')
	es_username = es.getplayername(userid)
	es_steamid = playerlib.uniqueid(userid,True)
	es.event('setint','player_ability_off','userid',userid)
	es.event('setstring','player_ability_off','es_steamid',es_steamid)
	es.event('setstring','player_ability_off','es_username',es_username)
	es.event('fire','player_ability_off')
#Handels our pre event commands
def prep_spawn():
	userid = int(return_EV('userid'))
	Command(userid).ResetDefault()
#Local Events (Contains Userids Ect.)
def player_team(event_var):
	userid = int(event_var['userid'])
	if Race(GetRace(userid)).returnRaceKey().has_key('teamlimit'):
		limit = Race(GetRace(userid)).returnRaceKey()['teamlimit']
		team = int(es.getplayerteam(userid))
		count = 0
		if team == 2:
			filter = '#t'
		elif team == 3:
			filter = '#ct'
		for id in playerlib.getUseridList(filter):
			if GetRace(id) == choice:
				count += 1
		if count >= limit:
			es.tell(userid, '#multi', '#defaultThe team you just joined already has the maxium number of #green%s #default allowed.'%(GetRace(userid)))
			defaultrace(userid, playerlib.uniqueid(int(userid),True))
def player_spawn(event_var):
	uid = int(event_var['userid'])
	BuyItem(uid).Update()
	for item in ShopMenuDict:
		if 'spawn' in ShopMenuDict[item]['fire']:
			if item in ShopPlayers[uid]['items']:
				function = ShopMenuDict[item]['function']
				if callable(function):
					function({'userid':uid,'type':'spawn','userteam':int(event_var['es_userteam'])})
def player_jump(event_var):
	uid = int(event_var['userid'])
	BuyItem(uid).Update()
	for item in ShopMenuDict:
		if 'jump' in ShopMenuDict[item]['fire']:
			if item in ShopPlayers[uid]['items']:
				function = ShopMenuDict[item]['function']
				if callable(function):
					function({'userid':uid,'type':'jump','userteam':int(event_var['es_userteam'])})
def item_pickup(event_var):
	uid = int(event_var['userid'])
	BuyItem(uid).Update()
	for item in ShopMenuDict:
		if 'pickup' in ShopMenuDict[item]['fire']:
			if item in ShopPlayers[uid]['items']:
				function = ShopMenuDict[item]['function']
				if callable(function):
					function({'userid':uid,'type':'pickup','userteam':int(event_var['es_userteam'])})
	userid = int(event_var['userid'])
	race = GetRace(userid)
	racekey = Race(race).returnRaceKey()
	if racekey.has_key('restriction type'):
		if event_var['item'] != 'c4':
			if racekey['restriction type'] == 'allow only':
				if event_var['item'] not in racekey['weapons list']:
					es.server.queuecmd('est_removeweapon %s weapon_%s'%(userid, event_var['item']))
			elif racekey['restriction type'] == 'block only':
				if event_var['item'] in racekey['weapons list']:
					es.server.queuecmd('est_removeweapon %s weapon_%s'%(userid, event_var['item']))
def player_hurt(event_var):
	uid = int(event_var['userid'])
	atk = int(event_var['attacker'])
	BuyItem(uid).Update()
	BuyItem(atk).Update()
	for item in ShopMenuDict:
		if 'userhurt' in ShopMenuDict[item]['fire']:
			if item in ShopPlayers[uid]['items']:
				function = ShopMenuDict[item]['function']
				if callable(function):
					function({'userid':uid,'attacker':atk,'damage':int(event_var['dmg_health']),'type':'hurt','userteam':int(event_var['es_userteam']),'attackerteam':int(event_var['es_attackerteam'])})
		if 'attackerhurt' in ShopMenuDict[item]['fire']:
			if item in ShopPlayers[atk]['items']:
				function = ShopMenuDict[item]['function']
				if callable(function):
					function({'userid':uid,'attacker':atk,'damage':int(event_var['dmg_health']),'type':'hurt','userteam':int(event_var['es_userteam']),'attackerteam':int(event_var['es_attackerteam'])})
	global dict_commands
	if dict_commands.has_key(uid) and not dict_commands[uid]['RegenLoop']:
		dict_commands[uid]['RegenLoop'] = 1
def player_disconnect(event_var):
	uid = int(event_var['userid'])
	if dict_commands.has_key(uid):
		del dict_commands[uid]
def player_death(event_var):
	userid = int(event_var['userid'])
	attacker = int(event_var['attacker'])
	BuyItem(userid).Update()
	BuyItem(attacker).Update()
	user_team = int(event_var['es_userteam'])
	attacker_team = int(event_var['es_attackerteam'])
	headshot = int(event_var['headshot'])
	for item in ShopMenuDict:
		if 'userdeath' in ShopMenuDict[item]['fire']:
			if item in ShopPlayers[userid]['items']:
				function = ShopMenuDict[item]['function']
				if callable(function):
					function({'userid':userid,'attacker':attacker,'type':'death','userteam':int(event_var['es_userteam']),'attackerteam':int(event_var['es_attackerteam'])})
		if 'attackerdeath' in ShopMenuDict[item]['fire']:
			if item in ShopPlayers[attacker]['items']:
				function = ShopMenuDict[item]['function']
				if callable(function):
					function({'userid':userid,'attacker':attacker,'type':'death','userteam':int(event_var['es_userteam']),'attackerteam':int(event_var['es_attackerteam'])})
	if attacker:
		if attacker_team != user_team:
			if killxp:
				Command(attacker).GiveXp(killxp, 'scoring a kill')
			if headshot:
				if headshotxp:
					Command(attacker).GiveXp(headshotxp, 'scoring a head shot')
			if event_var['weapon'] == 'knife':
				if knifexp:
					Command(attacker).GiveXp(knifexp, 'killing someone with a knife')
	uid = int(event_var['userid'])
	BuyItem(uid).ClearItems()
	if dict_commands.has_key(uid) and dict_commands[uid]['RegenLoop']:
		dict_commands[uid]['RegenLoop'] = 0
	if dict_commands.has_key(uid) and dict_commands[uid]['DrainLoop']:
		drain_delayed = 'drain_%s'%uid
		gamethread.cancelDelayed(drain_delayed)
		dict_commands[uid]['DrainLoop'] = 0
def hostage_rescued_all(event_var):
	if allhostagexp:
		for userid in playerlib.getUseridList('#ct,#alive'):
			Command(userid).GiveXp(allhostagexp, 'helping rescue all the hostages')
#Gets/Sets event_var for our prep events
def return_EV(type):
	es.server.cmd('est_geteventinfo wcs_temp %s'%type)
	return str(es.ServerVar('wcs_temp'))
def set_EV(type, value):
	es.server.cmd('est_seteventinfo %s %s'%(type, value))
#This code handles our user data base
_dict_WCSPlayers = {}
def getSteam(userid):
	global _dict_WCSPlayers
	steamid = playerlib.uniqueid(int(userid),True)
	if not _dict_WCSPlayers.has_key(steamid):
		helpmenu(userid)
		_dict_WCSPlayers[steamid] = {}
		defaultrace(userid, steamid)
	return _dict_WCSPlayers[steamid]
def player_activate(ev):
	steamid = playerlib.uniqueid(ev['userid'],True)
	if _dict_WCSPlayers.has_key(steamid):
		_dict_WCSPlayers[steamid]['name'] = ev['es_username']
		_dict_WCSPlayers[steamid]['last_active'] = time.time()
def defaultrace(userid, steamid):
	_dict_WCSPlayers[steamid]['level'] = 1
	_dict_WCSPlayers[steamid]['race'] = race_list[0]
	_dict_WCSPlayers[steamid]['delayed race'] = 0
	_dict_WCSPlayers[steamid]['last_active'] = time.time()
	_dict_WCSPlayers[steamid]['name'] = es.getplayername(userid)
	checkRace(userid, race_list[0])
def checkRace(userid, race):
	steamid = playerlib.uniqueid(userid,True)
	userKey = _dict_WCSPlayers[steamid]
	if not userKey.has_key(race):
		userKey[race] = {}
		userKey[race]['level'] = 1
		userKey[race]['xp'] = 0
		userKey[race]['unspent skills'] = 0
	for skill in Race(race).returnSkillList():
		if not userKey[race].has_key(skill):
			userKey[race][skill] = 0
#Handles return blocks for different values in our user file
def GetRace(userid):
	return getSteam(userid)['race']
def GetLevel(userid, raceName, skillName):
	race = GetRace(int(userid))
	if race == raceName:
		if Race(raceName).has_key(skillName):
			return getSteam(userid)[raceName][skillName]
		else:
			return 0
	else:
		return 0
# Mimics the 'spendskills' popup for bots, builds a list
# of available skills, then changes the race if its maxed
# out all of its skills.		
def BotLevel(userid,steamid):
	race = GetRace(userid)
	playerkey = getSteam(userid)[race]
	playerlevel = playerkey['level']
	skilllist = Race(race).returnSkillList()
	random_list = []
	skillskey = _dict_races[race]['skills']
	maximums = 0
	if playerkey['unspent skills']:
		for a in skilllist:
			level = GetLevel(userid, race, a)
			currentranks = playerkey[a]
			if skillskey[a]['type'] == 'Skill':
				if currentranks < skillskey[a]['levels']:
					intcheck = intervalCheck(currentranks, skillskey[a]['interval'], playerlevel)
					if intcheck:
						random_list.append(a)
				else:
					maximums += 1
			else:
				if currentranks < skillskey[a]['levels']:
					requiredlevel = skillskey[a]['levels']
					if playerlevel >= requiredlevel:
						intcheck = intervalCheck(currentranks, skillskey[a]['interval'], playerlevel - requiredlevel)
						if intcheck:
							random_list.append(a)
				else:
					maximums += 1
		if random_list:
			random_skill = random.choice(random_list)
			spendSelect(userid, (race, random_skill), None)
			BotLevel(userid,steamid)
		else:
			if maximums >= len(skilllist):
				# All the skills maxed out, change race.
				random_list = []
				player_team = int(es.getplayerteam(userid)) 
				for race in race_list:
					racekey = Race(race).returnRaceKey()
					if racekey.has_key('Min Level') and not racekey.has_key('Team'):
						if playerlevel >= racekey['Min Level']:
							random_list.append(race)
					elif racekey.has_key('Team') and not racekey.has_key('Min Level'):
						if player_team == racekey['Team']:
							random_list.append(race)
					elif racekey.has_key('Team') and racekey.has_key('Min Level'):
						if player_team == racekey['Team'] and playerlevel >= racekey['Min Level']:
							random_list.append(race)
					else:
						random_list.append(race)
				if random_list:
					random_skill = random.choice(random_list)
					raceMenuSelect(userid,random_skill,0)
					
class Effect:
	def __init__(self):
		pass
	def Smoke(self, player):
		# Smoke effect
		x,y,z = es.getplayerlocation(player)
		es.server.queuecmd('est_effect 7 #a 0 sprites/smoke.vmt %s %s %s 100 20'%(x,y,z))
	def Ring1(self, player, end, life, r, g, b):
		# Normal beam effect.
		x,y,z = es.getplayerlocation(player)
		es.server.queuecmd('est_effect 10 #a 0 "sprites/lgtning.vmt" %s %s %s 1 %s %s 10 20 10 %s %s %s 255 30'%(x,y,z,end,life,r,g,b))
	def Ring2(self, player, diameter, life, r, g, b):
		# A ring which doesn't move... static circle
		x,y,z = es.getplayerlocation(player)
		es.server.queuecmd('est_effect 10 #a 0 sprites/lgtning.vmt %s %s %s %s %s %s 5 0 2 %s %s %s 128 10'%(x,y,z,diameter-20,diameter,life,r,g,b))
	def Ring3(self, player, end, life, r, g, b):
		# A very 'harsh' ring which has a big amplitude.
		x,y,z = es.getplayerlocation(player,end,life,r,g,b)
		es.server.queuecmd('est_Effect 10 #a 0 sprites/xfireball3.vmt %s %s %s 20 %s %s 10 20 150 %s %s %s 200 100'%(x,y,z,end,life,r,g,b))
	def Follow(self, player, r, g, b):
		# Follows the user wherever he goes until he stops
		es.server.queuecmd('est_effect 4 #a 0 sprites/steam1.vmt %s 1 5 5 1 %s %s %s 200'%(player,r,g,b))
	def Beam1(self,player1,player2,life,r,g,b):
		# Connects 2 users together via a normal beam
		x,y,z = es.getplayerlocation(player1)
		x1,y1,z1 = es.getplayerlocation(player2)
		es.server.queuecmd('est_effect 3 #a 0 sprites/lgtning.vmt %s %s %s %s %s %s %s 40 10 %s %s %s 255'%(x,y,z,x1,y1,z1,life,r,g,b))
	def Beam2(self,player1,player2,life,r,g,b):
		# Connects 2 users together via a more rough beam
		x,y,z = es.getplayerlocation(player1)
		x1,y1,z1 = es.getplayerlocation(player2)
		es.server.queuecmd('est_effect 3 #a 0 effects/tp_eyefx/tpeye3.vmt %s %s %s %s %s %s %s 7 3 %s %s %s 255'%(x,y,z,x1,y1,z1,life,r,g,b))
	def Misc1(self,player,life):
		# A crystal like effect where the user is.
		x,y,z = es.getplayerlocation(player)
		es.server.queuecmd('est_effect 10 #a 0 effects/tp_eyefx/tpeye3.vmt %s %s %s 9 0 %s 66 1 0 255 255 255 255 1'%(x,y,z,life))

dict_commands = {}
class Command:
	global dict_commands
	def __init__(self, userid):
		self.userid = int(userid)
		if not dict_commands.has_key(self.userid):
			dict_commands[self.userid] = {}
			dict_commands[self.userid]['RegenLoop'] = 0
			dict_commands[self.userid]['Gravity'] = 1.0
			dict_commands[self.userid]['DrainLoop'] = 0
			dict_commands[self.userid]['MaxHealth'] = 100
			dict_commands[self.userid]['MaxArmor'] = 0
			dict_commands[self.userid]['Speed'] = 1.0
			dict_commands[self.userid]['CoolDownTime'] = {'start':0,'CoolTime':0}
			dict_commands[self.userid]['Alpha'] = 255
			dict_commands[self.userid]['AlphaLoop'] = 0
		self.key = dict_commands[self.userid]
	def ReturnUserKey(self):
		return self.key
	def SetCoolDown(self, skill,amount):
		self.key['CoolDownTime'][skill] = {}
		self.key['CoolDownTime'][skill]['start'] = time.time()
		self.key['CoolDownTime'][skill]['CoolTime'] = amount
	def GetCoolDown(self, skill):
		startcd = self.key['CoolDownTime'][skill]['start']
		now = time.time()
		time_elapsed = now - startcd
		if time_elapsed <= self.key['CoolDownTime'][skill]['CoolTime']: return (self.key['CoolDownTime'][skill]['CoolTime'] - time_elapsed)
		return 0
	def ResetDefault(self):
		self.key['RegenLoop'] = 0
		self.key['Gravity'] = 1.0
		es.server.queuecmd('est_SetGravity %s 1.0'%self.userid)
		self.key['DrainLoop'] = 0
		self.key['MaxHealth'] = 100
		self.key['MaxArmor'] = 0
		self.key['Speed'] = 1.0
		dict_commands[self.userid]['CoolDownTime'] = {'start':0,'CoolTime':0}
		self.key['Alpha'] = 255
		self.key['AlphaLoop'] = 0
	def UpdateDict(self, key, value):
		# Overwrites/sets a new value for a dict
		self.key[key] = value
	def ReturnDict(self, key):
		# Returns a value to a local variable
		if self.key.has_key(key): return self.key[key]
		else: es.dbgmsg(0,'WCS ERROR: There is no key in dict_commands called %s'%key)
	def ModDict(self, key, value):
		# Adds a value to the dict
		if self.key.has_key(key):
			self.key[key] += int(value)
		else: 
			es.dbgmsg(0,'WCS ERROR: There is no key in dict_commands called %s'%key)
	def Regen(self, AmountPerDelay, Delay):
		if self.key['RegenLoop']:
			health = int(es.getplayerprop(self.userid,'CBasePlayer.m_iHealth'))
			health += int(AmountPerDelay)
			MaxHealth = self.key['MaxHealth']
			if health <= int(MaxHealth) and not int(es.getplayerprop(self.userid,'CBasePlayer.pl.deadflag')):
				es.setplayerprop(self.userid,'CBasePlayer.m_iHealth',health)
				gamethread.delayed(int(Delay),self.Regen,(AmountPerDelay, Delay))
			else:
				es.setplayerprop(self.userid,'CBasePlayer.m_iHealth',MaxHealth)
				self.key['RegenLoop'] = 0
	def Damage(self, AmountOfDamage, DamageType=32, Attacker=0):
		es.server.queuecmd('damage %s %s %s %s'%(self.userid, AmountOfDamage, DamageType, Attacker))
	def Color(self, alpha=255, cColor=None, red=255, green=255, blue=255):
		if cColor:
			if colors.has_key(cColor):
				r,g,b = colors[cColor]
				es.server.queuecmd('est_SetPlayerColor %s %s %s %s %s 1'%(self.userid,r,g,b,alpha))
			else:
				es.dbgmsg(0,'WCS ERROR: No color named %s'%cColor)
		else:
			es.server.queuecmd('est_SetPlayerColor %s %s %s %s %s 1'%(self.userid,red,green,blue,alpha))
	def Fade(self, Alpha, Length):
		sAlpha = self.key['Alpha']
		self.key['AlphaLoop'] = 0
		if sAlpha >= Alpha: 
			tAlphaChange = sAlpha - Alpha
			tAlphaChange /= float(Length) # each second will fade this much
			tAlphaChange = int(round(tAlphaChange / 10.0)) # get milliseconds
			self.key['AlphaLoop'] = Length * 10
			gamethread.delayed(0.1,fadeplayer,(self.userid, tAlphaChange, False))
		else: 
			tAlphaChange = Alpha - sAlpha
			tAlphaChange /= float(Length) # each second will fade this much
			tAlphaChange = int(round(tAlphaChange / 10.0)) # get milliseconds
			self.key['AlphaLoop'] = Length * 10
			gamethread.delayed(0.1,fadeplayer,(self.userid, tAlphaChange, True))
	def Freeze(self, delay):
		if delay:
			es.server.queuecmd('est_freeze %s 1'%self.userid)
			gamethread.delayed(int(delay),es.server.queuecmd,'est_freeze %s 0'%self.userid)
		else:
			es.dbgmsg(0,'WCS ERROR: Cannot delay \'freeze\' command for %s seconds!'%delay)
	def God(self, delay):
		if delay:
			es.server.queuecmd('est_god %s 1'%self.userid)
			gamethread.delayed(int(delay),es.server.queuecmd,'est_god %s 0'%self.userid)
		else:
			es.dbgmsg(0,'WCS ERROR: Cannot delay \'God\' command for %s seconds!'%delay)
	def Blind(self, delay, alpha=255):
		if delay:
			es.server.queuecmd('est_Fade %s 1 %s 0 0 0 %s'%(self.userid, delay, alpha))
		else:
			es.dbgmsg(0,'WCS ERROR: Cannot delay \'Blind\' command for %s seconds!'%delay)
	def Burn(self, delay):
		if delay:
			es.server.queuecmd('est_Burn %s %s'%(self.userid,delay))
		else:
			es.dbgmsg(0,'WCS ERROR: Cannot delay \'Burn\' command for %s seconds!'%delay)
	def ChangeGravity(self, amount):
		if abs(amount):
			current_grav = dict_commands[self.userid]['Gravity']
			current_grav += amount
			if current_grav:
				es.server.queuecmd('est_SetGravity %s %s'%(self.userid,current_grav))
				dict_commands[self.userid]['Gravity'] = current_grav
			else:
				es.dbgmsg(0,'WCS ERROR: Cannot change %s\'s gravity to %s'%(es.getplayername(self.userid),current_grav))
		else:
			es.dbgmsg(0,'WCS ERROR: Cannot alter the ChangeGravity skill with a value of 0')
	def SetGravity(self, amount):
		if amount:
			dict_commands[self.userid]['Gravity'] = amount
			es.server.queuecmd('est_SetGravity %s %s'%(self.userid, amount))
		else:
			es.dbgmsg(0,'WCS ERROR: Cannot change %s\'s gravity to %s'%(es.getplayername(self.userid),amount))
	def Speed(self, amount):
		if amount:
			dict_commands[self.userid]['Speed'] = amount
			es.server.queuecmd('est_Speed %s %s'%(self.userid, amount))
		else:
			es.dbgmsg(0,'WCS ERROR: Cannot change %s\'s speed to %s'%(es.getplayername(self.userid), amount))
	def SpeedAdd(self, amount):
		if abs(amount):
			cur_speed = dict_commands[self.userid]['Speed']
			cur_speed += amount
			if cur_speed:
				es.server.queuecmd('est_Speed %s %s'%(self.userid, cur_speed))
				dict_commands[self.userid]['Speed'] = cur_speed
			else:
				es.dbgmsg(0,'WCS ERROR: Cannot change %s\'s speed to %s'%(es.getplayername(self.userid), cur_speed))
		else:
			es.dbgmsg(0,'WCS ERROR: Cannot add %s speed to %s'%(amount,es.getplayername(self.userid)))
	def Heal(self, amount):
		health = int(es.getplayerprop(self.userid, 'CBasePlayer.m_iHealth'))
		health += amount
		max_health = dict_commands[self.userid]['MaxHealth']
		if health <= max_health:
			es.setplayerprop(self.userid, 'CBasePlayer.m_iHealth',health)
		else:
			es.setplayerprop(self.userid,'CBasePlayer.m_iHealth',max_health)
	def Health(self, amount):
		if amount:
			dict_commands[self.userid]['MaxHealth'] = amount
			es.setplayerprop(self.userid,'CBasePlayer.m_iHealth',amount)
		else:
			es.dbgmsg(0,'WCS ERROR: Cannot change %s\'s health to %s'%(es.getplayername(self.userid), amount))
	def HealthAdd(self, amount):
		if abs(amount):
			cur_health = int(es.getplayerprop(self.userid,'CBasePlayer.m_iHealth'))
			cur_health += amount
			if cur_health > 0:
				dict_commands[self.userid]['MaxHealth'] = cur_health
				es.setplayerprop(self.userid,'CBasePlayer.m_iHealth',cur_health)
			else:
				es.dbgmsg(0,'WCS ERROR: Cannot change %s\'s health to %s'%(es.getplayername(self.userid), cur_health))
		else:
			es.dbgmsg(0,'WCS ERROR: Cannot add %s health to %s'%(amount,es.getplayername(self.userid)))
	def Armor(self, amount):
		if amount:
			dict_commands[self.userid]['MaxArmor'] = amount
			es.setplayerprop(self.userid,'CCSPlayer.m_ArmorValue',amount)
		else:
			es.dbgmsg(0,'WCS ERROR: Cannot change %s\'s health to %s'%(es.getplayername(self.userid),amount))
	def ArmorAdd(self, amount):
		if abs(amount):
			cur_armor = int(es.getplayerprop(self.userid,'CCSPlayer.m_ArmorValue'))
			cur_armor += int(amount)
			if cur_armor < 0: cur_armor = 0
			dict_commands[self.userid]['MaxArmor'] = cur_armor
			es.setplayerprop(self.userid,'CCSPlayer.m_ArmorValue',cur_armor)
		else:
			es.dbgmsg(0,'WCS ERROR: Cannot add %s health to %s'%(amount,es.getplayername(self.userid)))
	def Clip(self, amount, slot):
		a = playerlib.getPlayer(self.userid)
		a.set('clip', [str(slot), amount])
	def ClipAdd(self, amount, slot):
		a = playerlib.getPlayer(self.userid)
		clip = int(a.get('clip',str(slot)))
		clip += amount
		a.set('clip', [str(slot), clip])
	def Ammo(self, amount, slot):
		a = playerlib.getPlayer(self.userid)
		a.set('ammo', [str(slot), amount])
	def AmmoAdd(self, amount, slot):
		a = playerlib.getPlayer(self.userid)
		ammo = int(a.get('ammo',str(slot)))
		ammo += amount
		a.set('ammo', [str(slot), clip])
	def Drain(self, damage, delay, time):
		if time:
			if not self.key['DrainLoop']:
				self.key['DrainLoop'] = 1
				drain_delay = 'drain_%s'%self.userid
				gamethread.delayedname(int(time), drain_delay, self.ResetDrain)
			cur_health = int(es.getplayerprop(self.userid, 'CBasePlayer.m_iHealth'))
			cur_health -= int(damage)
			if cur_health > 0:
				es.setplayerprop(self.userid, 'CBasePlayer.m_iHealth', cur_health)
				gamethread.delayed(int(delay), self.Drain, (damage, delay, time))
			else:
				gamethread.cancelDelayed('drain_%s'%self.userid)
				es.server.queuecmd('damage %s 1'%self.userid)
		else:
			es.dbgmsg(0,'WCS ERROR: You must display a time delay for command(userid).Drain')
	def ResetDrain(self):
		self.key['DrainLoop'] = 0
	def Drop(self):
		es.sexec(self.userid,'drop')
	def Drug(self,time=None):
		es.server.queuecmd('est_Drug %s %s'%(self.userid,time))
	def Drunk(self,time=None):
		es.server.queuecmd('est_Drunk %s %s'%(self.userid,time))
	def GetViewAngles(self):
		'''
		Returns a list of Pitch, Yaw, Roll
		Either use it in
		angles = wcs.Command(userid).GetViewAngles
		angles = [pitch, yaw, roll]
		or...
		pitch, yaw, roll = wcs.Command(userid).GetViewAngles
		pitch = pitch
		yaw = yaw
		roll = roll
		'''
		hes.server.cmd('est_GetViewAngles %s wcs_x wcs_y wcs_z'%self.userid)
		return [float(es.ServerVar('wcs_x')),float(es.ServerVar('wcs_y')),float(es.ServerVar('wcs_z'))]
	def GetViewCoord(self):
		es.server.cmd('est_GetViewCoord %s wcs_x wcs_y wcs_z'%self.userid)
		return [float(es.ServerVar('wcs_x')), float(es.ServerVar('wcs_y')), float(es.Servervar('wcs_z'))]
	def GetViewPlayer(self):
		''' wcs_x is a variable for the userid he is looking at '''
		es.server.cmd('est_GetViewPlayer %s wcs_x'%self.userid)
		target = int(es.ServerVar('wcs_x'))
		if target:
			return target
		return None
	def GetViewProp(self):
		''' wcs_x is a variable for the prop index he is looking at '''
		es.server.cmd('est_GetViewProp %s wcs_x'%self.userid)
		prop_index = int(es.ServerVar('wcs_x'))
		if prop_index:
			return prop_index
		return None
	def ViewCone(self, filter, coneSize, coneDistance, method):
		es.ServerVar('wcs_x').set(self.userid)
		global ViewConeFn
		ViewConeFn = method
		es.server.cmd('est_viewcone wcs_y %s %s %s 0 %s "es_xdoblock wcs/ViewConeReturn"'%(self.userid, filter, coneSize, coneDistance))
	def NearCoord(self,x,y,z,function,ident='#all'):
		'''
		wcs.Command(userid).NearCoord(identifier,xrange,yrange,zrange,function)
		'''
		px,py,pz = es.getplayerlocation(self.userid)
		for player in playerlib.getPlayerList(ident):
			if int(player) != self.userid:
				qx,qy,qz = es.getplayerlocation(int(player))
				qx -= px
				qy -= py
				qz -= pz
				if abs(qx - px) <= x and abs(qy - py ) <= y and abs(qz - pz) <= z:
					if callable(function):
						function(int(player),self.userid)
	def Near(self,distance,function,ident='#all'):
		'''
		wcs.Command(userid).Near(identifier,range,function)
		'''
		x, y, z = es.getplayerlocation(self.userid)
		for player in playerlib.getPlayerList(ident):
			if int(player) != self.userid:
				xx, yy, zz = es.getplayerlocation(int(player))
				distanceb = ((x - xx) ** 2 + (y - yy) ** 2 + (z - zz) ** 2) ** 0.5
				if distanceb <= distance:
					if callable(function):
						function(int(player),self.userid)
	def Shake(self,time,violence):
		es.server.queuecmd('est_Shake %s %s %s %s'%(self.userid, time, violence, violence))
	def Model(self,path):
		es.server.queuecmd('est_SetModel %s "%s"'%(self.userid,path))
	def Spawn(self):
		es.server.queuecmd('est_spawn %s 1'%self.userid)
	def Push(self,x,y,z):
		es.server.queuecmd('est_PhysPush %s %s %s %s'%(self.userid,x,y,z))
	def PushTo(self,x,y,z,force):
		es.server.queuecmd('est_PushTo %s %s %s %s %s'%(self.userid,x,y,z,force))
	def AreaRegen(self,team,distance,amount,delay):
		es.server.cmd('est_near wcs_x %s %s %s "es wcs heal server_var(wcs_x) %s"'%(team,distance,self.userid, amount))
		gamethread.delayed(delay,self.AreaRegen,(team,distance,amount,delay))
	def AreaDamage(self,team,distance,amount):
		es.server.cmd('est_near wcs_x %s %s %s "es wcs damage server_var(wcs_x) %s"'%(team,distance,self.userid,amount))
	def GiveXp(self, amount, reason=""):
		_steamid = getSteam(self.userid)
		_race = GetRace(self.userid)
		_xp = _steamid[_race]['xp']
		_xp += int(amount)
		_level = _steamid[_race]['level']
		_total_level = _steamid['level']
		_nextlevelxp = (_level - 1) * levelinterval + start_your_engines
		_amount_of_levels = 0
		while _xp >= _nextlevelxp:
			_xp -= _nextlevelxp
			_amount_of_levels += 1
			_nextlevelxp += levelinterval
		if _amount_of_levels:
			self.GiveLevel(_amount_of_levels,"acquiring enough xp.")
		_steamid[_race]['xp'] = _xp
		if reason: 
			es.tell(self.userid, '#multi', '#greenYou have gained #lightgreen%s Xp#green%s.'%(amount, (" for " + reason)))
	def GiveLevel(self, amount, reason=None):
		_steamid = getSteam(self.userid)
		_race = GetRace(self.userid)
		if amount:
			good = 1
			if Race(_race).returnRaceKey().has_key('max level'):
				curlevel = _steamid[_race]['level']
				if not curlevel + amount <= Race(_race).returnRaceKey()['max level']:
					good = 0
			if good:
				_steamid[_race]['level'] += amount
				_steamid['level'] += amount
				_steamid[_race]['unspent skills'] += amount
				if not es.getplayerprop(self.userid,'CCSPlayer.baseclass.pl.deadflag'):
					location = es.getplayerlocation(self.userid)
					es.server.queuecmd('est_effect 10 #a 0 "sprites/steam1.vmt" %s %s %s 20 50 3 20 5 2 255 200 0 200 1'%(location[0],location[1],location[2]))
				es.emitsound('player',self.userid,'ambient/energy/whiteflash.wav','0.7','0.5')
				if es.getplayersteamid(self.userid) != "BOT":
					spendskills(self.userid)
				else:
					steam = playerlib.uniqueid(self.userid,True)
					BotLevel(self.userid,steam)
		if reason:
			es.tell(self.userid, '#multi', '#greenYou are now on level #lightgreen%s #green#default%s.'%(_steamid[_race]['level'],(" for " + reason)))
	def GetXp(self):
		_steamid = getSteam(self.userid)
		_race = GetRace(self.userid)
		_xp = _steamid[_race]['xp']
		return _xp
	def GetLevel(self):
		_steamid = getSteam(self.userid)
		_race = GetRace(self.userid)
		_level = _steamid[_race]['level']
		return _level
	def GetNextXp(self):
		_level = Command(self.userid).GetLevel()
		_next_level_xp = (int(_level) - 1) * levelinterval + start_your_engines
		return _next_level_xp
#Handles our est_viewcone wrapper
def ViewConeReturn():
	if callable(ViewConeFn):
		ViewConeFn(int(es.ServerVar('wcs_y')), int(es.ServerVar('wcs_x')))
# Handels our FadePlayer repeat loop
def fadeplayer(userid, alpha_change, addition):
	AlphaLoop = dict_commands[userid]['AlphaLoop']
	if AlphaLoop:
		AlphaLoop -= 1
		dict_commands[userid]['AlphaLoop'] = AlphaLoop
		Alpha = dict_commands[userid]['Alpha']
		if addition:
			Alpha += alpha_change
			if Alpha > 255: Alpha = 255
		else:
			Alpha -= alpha_change
			if Alpha < 0: Alpha = 0
		dict_commands[userid]['Alpha'] = Alpha
		es.server.queuecmd('est_SetPlayerColor %s 255 255 255 %s 1'%(userid, Alpha))
		gamethread.delayed(0.1,fadeplayer,(userid,alpha_change,addition)) 
#Handles Registering the different parts of our races
_dict_races = {}
class Race:
	def __init__(self, race):
		self.race = race
		global _dict_races
		if not _dict_races.has_key(race):
			_dict_races[race]= {}
			_dict_races[race]['skills'] = {}
			_dict_races[race]['skills']['skill list'] = []
		self.key = _dict_races[race]
		self.skills = self.key['skills']
	def registerSkill(self, skillName, skillLevels, skillInterval, skillDescription):
		self.skills[skillName] = {}
		self.skills[skillName]['type'] = 'Skill'
		self.skills[skillName]['levels'] = int(skillLevels)
		self.skills[skillName]['interval'] = int(skillInterval)
		self.skills[skillName]['description'] = skillDescription
		self.skills['skill list'].append(skillName)
	def registerMinLevel(self, minLevel):
		self.key['Min Level'] = minLevel
		buildracemenu()
	def registerTeam(self, Team):
		if Team.lower() == 't':
			regTeam = 2
		elif Team.lower() == 'ct':
			regTeam = 3
		elif Team in (2, 3):
			regTeam = Team
		else:
			es.dbgmsg(0,'Team %s is an incorect team for Race %s'%(Team,self.race))
			return None
		self.key['Team'] = regTeam
		buildracemenu()
	def registerUltimate(self, ultiName, ultiRequiredLevel, ultiMaxLevel, ultiLevelInterval, ultiDescription):
		self.skills[ultiName] = {}
		self.skills[ultiName]['type'] = 'Ulti'
		self.skills[ultiName]['required level'] = int(ultiRequiredLevel)
		self.skills[ultiName]['levels'] = int(ultiMaxLevel)
		self.skills[ultiName]['interval'] = int(ultiLevelInterval)
		self.skills[ultiName]['description'] = ultiDescription
		self.skills['skill list'].append(ultiName)
	def registerSteamid(self, steamIds):
		self.key['steam allow'] = steamIds
	def registerWeaponRestriction(self, type, weapons):
		if type.lower() == 'allow only':
			self.key['restriction type'] = 'allow only'
			self.key['weapons list'] = weapons
		elif type.lower() == 'block only':
			self.key['restriction type'] = 'block only'
			self.key['weapons list'] = weapons
	def registerMaxLevel(self, maxLevel):
		self.key['max level'] = maxLevel
	def registerTeamLimit(self, limit):
		self.key['teamlimit'] = int(limit)
	def returnSkillList(self):
		return self.skills['skill list']
	def returnRaceKey(self):
		return self.key
	def has_key(self, skillName):
		if self.skills.has_key(skillName):
			return 1
		else:
			return 0
# Class menu for the admin system
AdminDict = {}
class Admin:
	def __init__(self):
		global AdminDict
		self.dict = AdminDict
	def registerMenu(self, text, function):
		global AdminDict
		popup = popuplib.easymenu('wcsadminmenu','adminchoice',AdminSelection)
		popup.settitle('WarCraft Admin')
		self.dict[text] = function
		for a in self.dict:
			popup.addoption(a,a)
			#self.dict[a] = function
# Handels the admin selection functions	
def AdminSelection(userid, choice, popupid):
	if AdminDict.has_key(choice):
		function = AdminDict[choice]
		if callable(function):
			function(userid)
ShopMenuDict = {}
ShopPlayers = {}
class BuyItem:
	def __init__(self, userid):
		self.userid = int(userid)
		if self.userid:
			self.player_lib = playerlib.getPlayer(userid)
		global ShopPlayers
		if not ShopPlayers.has_key(self.userid):
			ShopPlayers[self.userid] = {}
			ShopPlayers[self.userid]['items'] = []
		self.items = ShopPlayers[self.userid]['items']
	def AddItem(self, item, cost):
		self.items.append(item)
	def Update(self):
		pass
	def ReturnNumberofItems(self):
		return len(self.items)
	def ClearItems(self):
		self.items = []
class ShopMenu:
	def __init__(self):
		global ShopMenuDict
		self.dict = ShopMenuDict
	def registerItem(self, name, section, cost, fire, function):
		if not self.dict.has_key(name):
			self.dict[name] = {}
			key = self.dict[name]
			key['cost'] = cost
			key['function'] = function
			key['fire'] = fire
			key['type'] = section
			if section == 'enhancement':
				popup = popuplib.easymenu('wcsenhancementmenu','itemchoice',ShopSelection)
				popup.settitle('WarCraft Shop Menu - Enhancements')
				for a in self.dict:
					if self.dict[a]['type'] == 'enhancement':
						popup.addoption(a,a+' ($%s)'%self.dict[a]['cost'])
				popup.submenu(0,'wcsshopmenu')
			elif section == 'powerup':
				popup = popuplib.easymenu('wcspowerupmenu','itemchoice',ShopSelection)
				popup.settitle('WarCraft Shop Menu - Power-Ups')
				for a in self.dict:
					if self.dict[a]['type'] == 'powerup':
						popup.addoption(a,a+' ($%s)'%self.dict[a]['cost'])
				popup.submenu(0,'wcsshopmenu')
			elif section == 'attack':
				popup = popuplib.easymenu('wcsattackmenu','itemchoice',ShopSelection)
				popup.settitle('WarCraft Shop Menu - Attacks')
				for a in self.dict:
					if self.dict[a]['type'] == 'attack':
						popup.addoption(a,a+' ($%s)'%self.dict[a]['cost'])
				popup.submenu(0,'wcsshopmenu')
			elif section == 'defense':
				popup = popuplib.easymenu('wcsdefensemenu','itemchoice',ShopSelection)
				popup.settitle('WarCraft Shop Menu - Defenses')
				for a in self.dict:
					if self.dict[a]['type'] == 'defense':
						popup.addoption(a,a+' ($%s)'%self.dict[a]['cost'])
				popup.submenu(0,'wcsshopmenu')
			elif section == 'special':
				popup = popuplib.easymenu('wcsspecialmenu','itemchoice',ShopSelection)
				popup.settitle('WarCraft Shop Menu - Specials')
				for a in self.dict:
					if self.dict[a]['type'] == 'special':
						popup.addoption(a,a+' ($%s)'%self.dict[a]['cost'])
				popup.submenu(0,'wcsshopmenu')
def ShopSelection(userid, choice, popupid):
	if ShopMenuDict.has_key(choice):
		cost = int(ShopMenuDict[choice]['cost'])
		if not int(es.getplayerprop(userid,'CCSPlayer.m_iAccount')) >= cost:
			es.tell(userid,'#multi','#greenYou do not have enough money to buy the #default%s#green.'%choice)
			return
		es.setplayerprop(userid,'CCSPlayer.m_iAccount',int(es.getplayerprop(userid,'CCSPlayer.m_iAccount')) - cost)
		es.tell(userid,'#multi','#greenYou have just purchased #default%s#green.'%choice)
		if BuyItem(userid).ReturnNumberofItems() < maxitems:
			if 'onbuy' in ShopMenuDict[choice]['fire']:
				function = ShopMenuDict[choice]['function']
				if 'onetime' not in ShopMenuDict[choice]['fire']:
					BuyItem(userid).AddItem(choice,cost)
				if callable(function):
					function({'userid':userid,'type':'onbuy','team':int(es.getplayerteam(userid))})
			else:
				BuyItem(userid).AddItem(choice,cost)
		else:
			self.player_lib.set('cash', self.player_lib.get('cash')+cost)
def SendRank(userid):
    """
    Sorted the dict out by level, then returns the index of the user.
    """
    a = sorted(_dict_WCSPlayers,WcsSort)
    steamid = playerlib.uniqueid(userid, True)
    position = a.index(steamid) + 1
    totalranked = len(a)
    _level = _dict_WCSPlayers[steamid]['level']
    _race = GetRace(userid)
    es.msg('#multi','#greenPlayer #default%s #greenis ranked #default%s/%s #greenwith Race: #default%s #greenTotal Level: #default%s'%(es.getplayername(userid),position,totalranked,_race,_level))
def WcsSort(player1, player2):
	if _dict_WCSPlayers[player1]['level'] > _dict_WCSPlayers[player2]['level']: return -1
	if _dict_WCSPlayers[player1]['level'] == _dict_WCSPlayers[player2]['level']: return 0
	return 1
